package aliyun

import (
	"bytes"
	"crypto/tls"
	"errors"
	"fmt"
	"github.com/aliyun/aliyun-oss-go-sdk/oss"
	"github.com/sirupsen/logrus"
	"io/ioutil"
	"micro-grpc-server/common"
	"micro-grpc-server/library/rand"
	"micro-grpc-server/library/upload"
	"net/http"
	"path"
	"strings"
	"time"
)

type Client struct {
	Client *oss.Client
	conf   *Configuration
}

func NewClient(conf *Configuration) *Client {
	return &Client{
		Client: nil,
		conf:   conf,
	}
}

func (c *Client) getClient() *oss.Client {
	client, err := oss.New(fmt.Sprintf("http://%s.aliyuncs.com", c.conf.BucketPoint), c.conf.AccessKey, c.conf.AccessKeySecret)
	if err != nil {
		logrus.Error(fmt.Sprintf("阿里云Oss客户端实例化失败-> %s", err.Error()))
		return nil
	}

	return client
}

func (c *Client) getBucket() (*oss.Bucket, error) {
	if c.Client == nil {
		return nil, errors.New("阿里云Oss客户端实例化失败 请检测配置文件")
	}
	return c.Client.Bucket(c.conf.Bucket)
}

func (c *Client) UploadImg(img *upload.ImgResource) (string, error) {
	var (
		bucket *oss.Bucket
		err    error
		url    string
	)
	bucket, err = c.getBucket()
	if err != nil {
		return "", err
	}
	url = fmt.Sprintf("avatar/%s/%s", time.Now().Format("20060102"), rand.RandomString(20))
	if strings.HasPrefix(img.Path, "http") {
		b, err := c.loadImageFormHttp(img.Path)
		if err != nil {
			return "", err
		}
		if ext := common.ImageFileExt(b); ext != "" {
			url += ext
		}
		err = bucket.PutObject(url, bytes.NewReader(b))
		fmt.Println(err)
	} else {
		if ext := path.Ext(img.Path); ext != "" {
			url += ext
		}
		err = bucket.PutObjectFromFile(url, img.Path)
	}
	if err != nil {
		return "", err
	}

	return fmt.Sprintf("%s/%s", c.conf.Host, url), nil
}

func (c *Client) loadImageFormHttp(file string) ([]byte, error) {
	tr := &http.Transport{
		TLSClientConfig: &tls.Config{
			InsecureSkipVerify: true,
		},
	}
	client := &http.Client{Transport: tr}
	res, err := client.Get(file)
	// 为什么要设置两次关闭通道
	// 如果这里返回的是重定向 则不能关闭 将会造成内存泄漏
	if res != nil {
		defer res.Body.Close()
	}
	if err != nil {
		return nil, err
	}
	defer res.Body.Close()

	return ioutil.ReadAll(res.Body)
}
